<!--
 * @description: 视频生成
 * @fileName: index
 * @author: 17076
 * @date: 2025/4/15-下午1:19
 * @version: V1.0.0
-->

<template>
  <div>
    <page-header @back="() => { $router.back() }" />
    <el-row :gutter="10" style="margin-top: 10px">
      <el-col :span="6">
        <base-card class="edit-content" :style="{ height: $baseTableHeight(-115) + 'px' }">
          <div slot="header"/>
          <div style="text-align: center">
            <el-segmented v-model="activeTabs" :options="tabs" />
          </div>
          <div
            class="edit-form-content"
          >
            <el-form ref="form" :model="editForm" :rules="rules" label-width="90px" label-position="top">
              <el-form-item label="提示词" prop="prompt">
                <el-popover v-model="showRolePopup" placement="right" trigger="manual" popper-class="prompt-popup">
                  <!-- 角色选择弹窗 -->
                  <div class="role-popup">
                    <div
                      v-for="item in rolesList"
                      :key="item.id"
                      class="role-item"
                      @click="handleInsertRole(item)"
                    >
                      {{ item.name }}
                    </div>
                  </div>
                  <div ref="prompt" slot="reference" :class="['prompt-content', isFullscreen ? 'prompt-content-full' : '']">
                    <el-input
                      v-model="editForm['prompt']"
                      type="textarea"
                      :rows="6"
                      placeholder="请输入提示词"
                      @keydown.native="handleKeyDown"
                      @input.native="handleInput"
                    />
                    <i v-if="translating" class="el-icon-loading change-loading" />
                  </div>
                </el-popover>
                <el-tooltip placement="top" content="智能推荐">
                  <svg-icon icon-class="prompt_recommend" class="prompt-recommend" @click="handleRecommend(editForm.prompt)" />
                </el-tooltip>
                <svg-icon :icon-class="formatterLanguageIcon(editForm['prompt'])" class="prompt-language" @click="handleLanguageChange(editForm.prompt)" />
                <!--                    <svg-icon icon-class="copy" class="prompt-copy" @click="handleCopyPrompt(editForm.prompt)" />-->
              </el-form-item>
              <el-form-item label="参考素材" prop="referenceMaterial">
                <el-upload
                  v-if="!editForm['referenceMaterial']"
                  class="upload-demo"
                  :action="uploadOption.action"
                  :headers="uploadOption.headers"
                  :on-remove="handleRemove"
                  :on-success="handleSuccess"
                  :limit="1"
                  drag
                  accept=".jpg,.png,.jpeg"
                  :file-list="fileList"
                  :show-file-list="false"
                >
                  <i class="el-icon-picture-outline" />
                  <div>点击<em>本地上传</em>或将图片拖拽到这里</div>
                  <div class="el-upload__tip">只能上传jpg/jpeg/png文件，且不超过10MB</div>
                </el-upload>
                <svg-icon
                  v-if="!editForm['referenceMaterial']"
                  icon-class="prompt_lens"
                  class="prompt-lens-icon"
                  @click="() => { $refs.select.show() }"
                />
                <div v-else class="prompt-image">
                  <el-image :src="downloadUrl + editForm['referenceMaterial']" />
                  <div class="flex-row prompt-image-toolbar">
                    <i class="el-icon-picture-outline" @click="handleUploadLens(false)" />
                    <i class="el-icon-camera" @click="() => { $refs.select.show() }" />
                    <i class="el-icon-delete" @click="handleRemove" />
                  </div>
                </div>
              </el-form-item>
              <el-form-item label="选择模型" prop="modelCode">
                <el-select v-model="editForm['modelCode']" clearable placeholder="请选择模型">
                  <el-option
                    v-for="item in modelList"
                    :key="item.code.toString()"
                    :label="item.name"
                    :value="item.code.toString()"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="生成数量" prop="createNum">
                <div class="flex-row create-num-content">
                  <span
                    v-for="item in createNumList"
                    :key="item.value"
                    :class="{ 'create-num-item': true, 'active': editForm['createNum'] === item.value }"
                    @click="handleCreateNumChange(item.value)"
                  >{{ item.name }}</span>
                </div>
              </el-form-item>
              <el-form-item label="画面比例" prop="pictureScale">
                <el-select v-model="editForm['pictureScale']" placeholder="请选择" @change="handleScaleChange">
                  <el-option
                    v-for="item in pictureScaleList"
                    :key="item.code"
                    :label="item['name']"
                    :value="item.code"
                  >
                    <div class="flex-row" style="align-items: center">
                      <div class="picture-scale-placeholder">
                        <div class="picture-scale-tag" :data-ratio="item.code" />
                      </div>
                      <span style="margin-left: 10px">{{ item['name'] }}</span>
                    </div>
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="图像大小" prop="pictureSize">
                <div class="flex-row create-num-content">
                  <el-input v-model="editForm.imageWidth" type="number" placeholder="图片宽" clearable />
                  <i
                    class="el-icon-link link-icon"
                    :style="{ color: editForm['isLink'] === '1' ? '#FFFFFF' : '#58636E' }"
                    @click="handleLinkChange(editForm['isLink'])"
                  />
                  <el-input v-model="editForm.imageHeight" type="number" placeholder="图片高" clearable />
                </div>
              </el-form-item>
              <el-form-item prop="steps">
                <template slot="label">
                  <div class="flex-row" style="align-items: center">
                    <span>采样迭代步数</span>
                    <span style="color: #B6C7D1;font-size: 12px;margin-left: 8px">(Sampling Steps)</span>
                    <el-tooltip effect="dark" content="步数越多,细节越好,但生成时间越长" placement="top-start">
                      <i class="el-icon-warning" style="color: #B6C7D1;margin-left: 8px" />
                    </el-tooltip>
                  </div>
                </template>
                <el-slider
                  v-model="editForm.steps"
                  :min="30"
                  :max="100"
                  show-input
                />
              </el-form-item>
              <el-form-item prop="cfg">
                <template slot="label">
                  <div class="flex-row" style="align-items: center">
                    <span>提示词相关性</span>
                    <span style="color: #B6C7D1;font-size: 12px;margin-left: 8px">(CFG Scale)</span>
                    <el-tooltip effect="dark" content="数值越大,创意性越强" placement="top-start">
                      <i class="el-icon-warning" style="color: #B6C7D1;margin-left: 8px" />
                    </el-tooltip>
                  </div>
                </template>
                <el-slider
                  v-model="editForm.cfg"
                  :min="0.00"
                  :max="100.00"
                  :step="0.01"
                  show-input
                />
              </el-form-item>
              <!--                    <el-form-item label="采样方法 (Sampler)" prop="sampler">
                <template slot="label">
                  <span>采样方法<i style="color: #B6C7D1;font-size: 12px;margin-left: 8px;font-style: normal">(Sampler)</i></span>
                </template>
                <el-select v-model="editForm['sampler']" :disabled="!editForm.modelCode" filterable clearable placeholder="请选择采样方法">
                  <el-option
                    v-for="item in samplerList"
                    :key="item.code"
                    :label="item.name"
                    :value="item.code"
                  />
                </el-select>
              </el-form-item>-->
              <el-form-item prop="seed">
                <template slot="label">
                  <div class="flex-row">
                    <span>随机种子</span>
                    <span style="color: #B6C7D1;font-size: 12px;margin-left: 8px">(Seed)</span>
                  </div>
                </template>

                <div class="flex-row" style="align-items: center">
                  <el-input-number v-model="editForm['seed']" placeholder="随机生成" class="seed-input" />
                  <i class="el-icon-refresh" style="cursor: pointer;font-size: 20px;margin-left: 8px" title="随机生成" @click="handleRandomGenerate" />
                </div>
              </el-form-item>
            </el-form>
          </div>
          <div class="flex-row edit-bottom-bar">
            <el-button class="liner-button" :loading="generateLoading" style="flex: 1" @click="startGenerate">开始生成</el-button>
          </div>
        </base-card>
      </el-col>
      <el-col :span="18">
        <base-card class="content" :style="{ height: $baseTableHeight(-115) + 'px' }">
          <div slot="header" />
          <el-empty description="暂无数据" style="width: 100%;height: 100%">
            <template slot="image">
              <img src="@/assets/common/empty_role.png" />
            </template>
          </el-empty>
        </base-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import fullscreen from 'screenfull'
import Swiper from 'swiper'
import 'swiper/css/swiper.css'
import { baseURL, wsUrl } from '@/config/net.config'
import { commonDownloadFile, commonSaveFile, commonUploadFile, deleteFile, uploadFile } from '@/api/config/uploadApi'
import { detectLanguage } from '@/utils'
import {
  addLensFrame,
  queryFrameHistory,
  queryLensCoverHistory,
  queryLensListByFrameId,
  textToImages,
  uploadFrameImage,
  moveLensFrame, deleteLensFrame, setLensFrame,
  deleteGenerateHistory,
  clearGenerateHistory, chineseToEnglish, queryUserFrameProgress, cancelLensFrame
} from '@/api/lens'
import WS from '@/utils/webScoket'
import { mapGetters } from 'vuex'
import SelectLens from '@/views/creativeCenter/playWriting/components/lens/others/SelectLens.vue'
import { selectPlayRole } from '@/api/roles'
export default {
  name: 'Index',
  components: { SelectLens },
  props: {
    playId: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      activeTabs: '1',
      tabs: [
        { label: '图生视频', value: '1' },
        { label: '文生视频', value: '2' },
        { label: '首尾帧生成', value: '3' }
      ],
      // ws 实例
      ws: null,
      // swiper实例
      swiper: null,
      // 是否显示图片预览
      showImageViewer: false,
      // 初始图片下标
      initialIndex: 0,
      // 当前选中的镜头下标
      currentLensIndex: 0,
      // 生成历史镜头下标
      currentGenerateHistoryImageId: null,
      // 选中历史镜头
      currentHistoryImage: 0,
      // 选中历史镜头数据
      currentHistoryImageData: {},
      // 选中的生成之后的图片下标
      currentGenerateImage: null,
      // 更多参数
      showDetails: false,
      // 正在生成
      generateLoading: false,
      // 正在翻译
      translating: false,
      // 是否显示提示词
      isShowPrompt: '1',
      // 图片宽高更新锁
      updateLock: false,
      // 提示词是否全屏
      isFullscreen: false,
      // 区分是提示词的本地图片上传还是，还是镜头上传
      isLensUpload: false,
      // 右侧镜头区更多参数显示
      showMore: true,
      // 显示角色弹窗
      showRolePopup: false,
      // 记录光标位置
      cursorPosition: 0,
      // 全部镜头列表
      allLensList: [],
      // 上传参数配置
      uploadOption: {
        action: baseURL + commonUploadFile,
        headers: {
          'Auth-Token': localStorage.getItem('MyToken')
        }
      },
      // 参考素材文件列表
      fileList: [],
      // 编辑区表单
      editForm: {
        steps: 30,
        createNum: '1',
        cfg: 5.45
      },
      // 预览图片连接
      previewImageUrl: '',
      // 编辑区校验规则
      rules: {
        modelCode: [{ required: true, message: '请选择模型!', trigger: 'blur' }],
        prompt: [{ required: true, message: '提示词不能为空!', trigger: 'blur' }],
        sampler: [{ required: true, message: '采样方法不能为空!', trigger: 'blur' }]
      },
      // 生成数量列表
      createNumList: [
        { name: '1 张', value: '1' },
        { name: '2 张', value: '2' },
        { name: '3 张', value: '3' },
        { name: '4 张', value: '4' }
      ],
      // 角色列表
      rolesList: [{ name: '12121', id: 0 }, { name: '2121212', id: 1 }],
      // 模型列表
      modelList: JSON.parse(sessionStorage.getItem('modelType')),
      // 质量等级
      qualityList: JSON.parse(sessionStorage.getItem('qualityLevel')),
      // 画面比例
      pictureScaleList: JSON.parse(sessionStorage.getItem('pictureScale')),
      // 采样方法
      samplerList: [],
      // 是否编辑
      isEdit: false,
      // 下载连接
      downloadUrl: baseURL + commonDownloadFile,
      // 生成历史
      generateHistoryList: [],
      // 历史镜头
      historyLensList: [],
      // 正在进行文生图的图片列表
      generatingList: [],
      // comfy-ui 当前正在执行的任务数量
      queueRemaining: 0
    }
  },
  computed: {
    // 分镜数据
    ...mapGetters({
      username: 'user/username',
      selectLens: 'lens/selectLens',
      // pictureScale: 'lens/pictureScale',
      directorSelectLensId: 'lens/directorSelectLensId'
    })
  },
  watch: {
    // 监听表单中图片宽高的变化
    'editForm.imageWidth': {
      handler: function(val) {
        if (this.updateLock) return
        // 需要宽高比存在链接关系才可同时设置高度
        if (val && this.editForm['isLink'] === '1') {
          this.updateLock = true
          // 根据当前图片的宽高比改变
          switch (this.editForm['pictureScale']) {
            case '1':
              // 21 : 9
              this.$set(this.editForm, 'imageHeight', (val * 9 / 21).toFixed(0))
              break
            case '2':
              // 16 : 9
              this.$set(this.editForm, 'imageHeight', (val * 9 / 16).toFixed(0))
              break
            case '3':
              // 3 : 2
              this.$set(this.editForm, 'imageHeight', (val * 2 / 3).toFixed(0))
              break
            case '4':
              // 4 : 3
              this.$set(this.editForm, 'imageHeight', (val * 3 / 4).toFixed(0))
              break
            case '5':
              // 1 : 1
              this.$set(this.editForm, 'imageHeight', val)
              break
            case '6':
              // 3 : 4
              this.$set(this.editForm, 'imageHeight', (val * 4 / 3).toFixed(0))
              break
            case '7':
              // 2 : 3
              this.$set(this.editForm, 'imageHeight', (val * 3 / 2).toFixed(0))
              break
            case '8':
              // 9 : 16
              this.$set(this.editForm, 'imageHeight', (val * 16 / 9).toFixed(0))
              break
          }
        }
        this.$nextTick(() => { this.updateLock = false })
      },
      deep: true
    },
    // 监听表单中图片宽高的变化
    'editForm.imageHeight': {
      handler: function(val) {
        if (this.updateLock) return
        // 需要宽高比存在链接关系才可同时设置高度
        if (val && this.editForm['isLink'] === '1') {
          this.updateLock = true
          // 根据当前图片的宽高比改变
          switch (this.editForm['pictureScale']) {
            case '1':
              // 21 : 9
              this.$set(this.editForm, 'imageWidth', (val * 21 / 9).toFixed(0))
              break
            case '2':
              // 16 : 9
              this.$set(this.editForm, 'imageWidth', (val * 16 / 9).toFixed(0))
              break
            case '3':
              // 3 : 2
              this.$set(this.editForm, 'imageWidth', (val * 3 / 2).toFixed(0))
              break
            case '4':
              // 4 : 3
              this.$set(this.editForm, 'imageWidth', (val * 4 / 3).toFixed(0))
              break
            case '5':
              // 1 : 1
              this.$set(this.editForm, 'imageWidth', val)
              break
            case '6':
              // 3 : 4
              this.$set(this.editForm, 'imageWidth', (val * 3 / 4).toFixed(0))
              break
            case '7':
              // 2 : 3
              this.$set(this.editForm, 'imageWidth', (val * 2 / 3).toFixed(0))
              break
            case '8':
              // 9 : 16
              this.$set(this.editForm, 'imageWidth', (val * 9 / 16).toFixed(0))
              break
          }
        }
        this.$nextTick(() => { this.updateLock = false })
      },
      deep: true
    },
    // 导演反馈选中的镜头id
    directorSelectLensId: {
      handler: function(newVal, oldVal) {
        if (newVal !== oldVal) {
          this.queryLensData()
        }
      },
      deep: true
    },
    // 监听选中的分镜数据有值才调用接口
    selectLens: {
      handler: function(newVal, oldVal) {
        if (newVal && newVal['lensId'] && newVal !== oldVal) {
          this.queryLensData()
        }
      },
      immediate: true
    }
  },
  mounted() {
    this.handleWs()
    this.queryRolesList()
    // this.queryLensData()
    // 提示词全屏监听
    if (fullscreen.isEnabled) {
      fullscreen.on('change', this.promptFullChange)
    }
  },
  beforeDestroy() {
    if (fullscreen.isEnabled) {
      fullscreen.off('change', this.promptFullChange)
    }
  },
  methods: {
    // 获取镜头数据
    queryLensData() {
      if (!this.selectLens['lensId']) {
        this.$baseMessage.error('请选择一条分镜数据!')
        return
      }
      queryLensListByFrameId({ lensId: this.selectLens['lensId'] }).then(res => {
        this.allLensList = res.data
        // 如果当前镜头id存在则选中当前镜头
        if (this.directorSelectLensId) {
          const index = this.allLensList.findIndex(item => item.id === this.directorSelectLensId)
          if (index !== -1) {
            this.currentLensIndex = index
          }
        }
        // 组合镜头数据
        this.handleShotDataCombination(this.currentLensIndex)
        // 查询任务进度
        this.handleQueryProgress()
        this.queryLensSettingCoverHistory()
        this.queryGenerateHistory()
      })
    },
    // 获取生成历史记录
    queryGenerateHistory() {
      if (!this.editForm['id'] && !this.editForm['frameId']) {
        this.$baseMessage.error('镜头id不能为空!')
        return
      }
      queryFrameHistory({ frameId: this.editForm['id'] || this.editForm['frameId'] }).then(res => {
        this.generateHistoryList = res.data
      })
    },
    // 获取镜头封面设置历史
    queryLensSettingCoverHistory() {
      if (!this.editForm['id'] && !this.editForm['frameId']) {
        this.$baseMessage.error('镜头id不能为空!')
        return
      }
      queryLensCoverHistory({ frameId: this.editForm['id'] || this.editForm['frameId'] }).then(res => {
        this.historyLensList = res.data
        this.currentHistoryImageData = res.data[this.currentHistoryImage] || {}
        this.initSwiper()
      })
    },
    // 获取角色列表
    queryRolesList() {
      selectPlayRole({ playId: this.playId }).then(res => {
        this.rolesList = res.data.result
        console.log('角色列表:', this.roleList)
      })
    },
    // 初始化swiper
    initSwiper() {
      if (this.swiper) {
        this.swiper.destroy()
        this.swiper = null
      }
      this.$nextTick(() => {
        // 初始化swiper
        this.swiper = new Swiper('.swiper-container', {
          loop: false,
          slidesPerView: 3,
          spaceBetween: 20,
          navigation: {
            nextEl: '.next-button', // 下一页按钮
            prevEl: '.pre-button' // 上一页按钮
          }
        })
      })
    },
    // 生成张数改变
    handleCreateNumChange(value) {
      this.$set(this.editForm, 'createNum', value)
    },
    // 格式化语言图标显示
    formatterLanguageIcon(text) {
      return detectLanguage(text) === 'ch' ? 'english' : 'chinese'
    },
    // 监听输入框输入
    handleInput(event) {
      // 获取输入内容和光标位置
      const inputData = event.data
      if (inputData && inputData === '#') {
        this.showRolePopup = true
        this.cursorPosition = event.target.selectionStart
        return
      }
      this.showRolePopup = false
    },
    // 监听提示词键盘输入
    handleKeyDown(e) {
      // 按下ESC关闭弹窗
      if (e.key === 'Escape') {
        this.showRolePopup = false
      }
    },
    // 插入提示词角色名称
    handleInsertRole(role) {
      const roleName = role['name'] + '#'
      // 根据记录的光标位置插入角色名称
      let modifiedString = this.editForm['prompt'].split('')
      modifiedString.splice(this.cursorPosition, 0, ...roleName)
      modifiedString = modifiedString.join('')
      this.$set(this.editForm, 'prompt', modifiedString)
      this.showRolePopup = false
    },
    // 语言切换
    handleLanguageChange(text) {
      if (!text) {
        this.$baseMessage.error('提示词不能为空!')
        return
      }
      if (this.translating) {
        this.$baseMessage.error('翻译中,请稍后再试!')
        return
      }
      // 调用接口翻译
      this.translating = true
      chineseToEnglish({ translationText: text }).then(res => {
        this.$set(this.editForm, 'prompt', res.data['translation'])
        this.translating = false
      }).catch(() => {
        this.translating = false
      })
    },
    // 智能推荐
    handleRecommend() {
      // 先前台合并提示词字段
      const prompt = `${this.selectLens['shotSizeName'] || '全景'}-${this.selectLens['lensTime'] || '早上'}-${this.selectLens['scenery']}`
      this.$set(this.editForm, 'prompt', prompt)
    },
    // 参考素材上传成功
    handleSuccess(response) {
      if (response['code'] === 200) {
        this.$set(this.editForm, 'referenceMaterial', response.data.id)
      }
    },
    // 参考素材文件删除
    handleRemove() {
      deleteFile(this.editForm['referenceMaterial']).then(res => {
        this.$set(this.editForm, 'referenceMaterial', '')
      })
    },
    // 提示词全屏
    handleTogglePromptFull() {
      if (!fullscreen.isEnabled) {
        this.$baseMessage.error('开启全屏失败')
        return false
      }
      fullscreen.toggle(this.$refs.prompt)
    },
    // 选择镜头选中
    handleLensCheck(data) {
      console.log(data)
      // 将镜头的图片id添加到参考素材中
      this.$set(this.editForm, 'referenceMaterial', data['imageId'])
    },
    // 复制提示词
    async handleCopyPrompt(text) {
      if (!text) {
        this.$baseMessage.error('文本为空!')
        return
      }
      if (navigator.clipboard && navigator.clipboard.writeText) {
        // 使用Clipboard API
        try {
          await navigator.clipboard.writeText(text)
          this.$baseMessage.success('文本已复制到剪切板')
        } catch (err) {
          // 回退到document.execCommand
          document.execCommand('copy', false, text)
          this.$baseMessage.success('文本已复制到剪切板')
        }
      } else {
        // 直接使用document.execCommand作为回退方案
        document.execCommand('copy', false, text)
        this.$baseMessage.success('文本已复制到剪切板')
      }
    },
    // 画面比例切换
    handleScaleChange(val) {
      // 非宽高比链接下不用切换宽高
      if (this.editForm['isLink'] !== '1') return
      switch (val) {
        case '1':
          // 21 : 9
          this.$set(this.editForm, 'imageWidth', 1024)
          this.$set(this.editForm, 'imageHeight', 456)
          break
        case '2':
          // 16: 9
          this.$set(this.editForm, 'imageWidth', 1920)
          this.$set(this.editForm, 'imageHeight', 1080)
          break
        case '3':
          // 3 : 2
          this.$set(this.editForm, 'imageWidth', 1080)
          this.$set(this.editForm, 'imageHeight', 720)
          break
        case '4':
          // 4: 3
          this.$set(this.editForm, 'imageWidth', 1280)
          this.$set(this.editForm, 'imageHeight', 960)
          break
        case '5':
          // 1 : 1
          this.$set(this.editForm, 'imageWidth', 960)
          this.$set(this.editForm, 'imageHeight', 960)
          break
        case '6':
          // 3 : 4
          this.$set(this.editForm, 'imageWidth', 960)
          this.$set(this.editForm, 'imageHeight', 1280)
          break
        case '7':
          // 2 : 3
          this.$set(this.editForm, 'imageWidth', 720)
          this.$set(this.editForm, 'imageHeight', 1080)
          break
        case '8':
          // 9 : 16
          this.$set(this.editForm, 'imageWidth', 1080)
          this.$set(this.editForm, 'imageHeight', 1920)
          break
      }
    },
    // 图片宽高链接点击
    handleLinkChange(val) {
      this.$set(this.editForm, 'isLink', val === '1' ? '0' : '1')
    },
    // 生成随机种子
    handleRandomGenerate() {
      // 生成0-999999999999999 的随机数
      const randomNum = Math.floor(Math.random() * Math.pow(10, 15))
      this.$set(this.editForm, 'seed', randomNum)
    },
    // 删除生成历史
    handleDeleteGenerate(item) {
      this.$baseConfirm('确定删除该条生成历史吗?', '提示', async() => {
        const { code, msg } = await deleteGenerateHistory({ taskId: item['taskId'], frameId: item['frameId'] })
        code === 200 ? this.$baseMessage.success(msg || '删除成功!') : this.$baseMessage.error(msg || '删除失败!')
        this.queryGenerateHistory()
      })
    },
    // 一键清空生成历史
    handleClearGenerate() {
      this.$baseConfirm('确定清空所有生成历史吗?', '提示', async() => {
        const { code, msg } = await clearGenerateHistory({ frameId: this.editForm['id'] || this.editForm['frameId'] })
        code === 200 ? this.$baseMessage.success(msg || '删除成功!') : this.$baseMessage.error(msg || '删除失败!')
        this.queryGenerateHistory()
      })
    },
    // 下载镜头图片
    handleDownloadLensFrameImage() {
      if (this.generatingList.length > 0) {
        if (!this.currentHistoryImageData['imageId']) {
          this.$baseMessage.error('当前没有图片可下载!')
          return
        }
        const downloadUrl = `${baseURL}${commonSaveFile}${this.currentHistoryImageData['imageId']}`
        const link = document.createElement('a')
        link.href = downloadUrl
        link.download = `${this.currentHistoryImageData['frameNo']}.jpg` // 可以根据需要修改文件名
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      } else {
        const currentGenerateImageData = this.generatingList[this.currentGenerateImage]
        if (!currentGenerateImageData['imageId']) {
          this.$baseMessage.error('当前没有图片可下载!')
          return
        }
        const downloadUrl = `${baseURL}${commonSaveFile}${currentGenerateImageData['imageId']}`
        const link = document.createElement('a')
        link.href = downloadUrl
        link.download = `${currentGenerateImageData['frameNo']}.jpg` // 可以根据需要修改文件名
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      }
    },
    // 设为镜头
    async handleSetLens(e, val) {
      if (e === '00') {
        const { code, msg } = await setLensFrame({ frameId: this.editForm['id'] || this.editForm['frameId'], imageId: val['imageId'] })
        code === 200 ? this.$baseMessage.success(msg || '设置分镜镜头成功!') : this.$baseMessage.error(msg || '设置分镜镜头失败!')
      } else {
        const { code, msg } = await cancelLensFrame({ frameId: this.editForm['id'] || this.editForm['frameId'], imageId: val['imageId'] })
        code === 200 ? this.$baseMessage.success(msg || '取消分镜镜头成功!') : this.$baseMessage.error(msg || '取消分镜镜头失败!')
      }
      // 直接选中设置封面的第一张
      this.currentHistoryImage = 0
      // 取消生成历史的选中下标
      this.currentGenerateHistoryImageId = null
      // 刷新数据
      this.queryLensData()
    },
    // 预览界面-放大查看镜头图片
    handleFullLensFrame() {
      if (this.generatingList.length > 0) {
        // 文生图成功之后的放大
        const currentGenerateImageData = this.generatingList[this.currentGenerateImage]
        if (!currentGenerateImageData['imageId']) {
          this.$baseMessage.error('当前没有图片可放大查看!')
          return
        }
        this.previewImageUrl = this.downloadUrl + currentGenerateImageData['imageId']
      } else {
        // 普通镜头的放大
        if (!this.currentHistoryImageData['imageId']) {
          this.$baseMessage.error('当前没有图片可放大查看!')
          return
        }
        this.previewImageUrl = this.downloadUrl + this.currentHistoryImageData['imageId']
      }
      this.showImageViewer = true
    },
    // 选中生成之后的图片
    handleGenerateSelectImage(item, index) {
      this.currentGenerateImage = index
    },
    // 上传镜头图片
    handleUploadLens(type) {
      this.isLensUpload = type
      this.$refs.fileInput.value = null
      this.$refs.fileInput.click()
    },
    // 图片上传选中文件
    handleFileChange(e) {
      const file = e.target.files[0]
      if (this.isLensUpload) {
        // 镜头图片上传
        const formData = new FormData()
        formData.append('file', file)
        formData.append('frameId', this.editForm.id)
        uploadFrameImage(formData).then(_ => {
          this.queryLensData()
        })
      } else {
        // 参考材料本地图片上传
        const formData = new FormData()
        formData.append('file', file)
        uploadFile(formData).then(res => {
          this.$set(this.editForm, 'referenceMaterial', res.data.id)
        })
      }
    },
    // 生成历史图片点击
    handleSelectImage(item, subItem) {
      console.log(item, 67676767)
      this.currentHistoryImageData = item
      this.$set(this.currentHistoryImageData, 'imageId', subItem.imageId)
      this.$set(this.currentHistoryImageData, 'currentFrame', subItem['currentFrame'])
      this.currentGenerateHistoryImageId = subItem.imageId
      // 清空历史镜头选中
      this.currentHistoryImage = null
      // 清空选中的生成之后的图片id
      this.currentGenerateImage = null
      // 清空生成历史列表
      this.generatingList = []
    },
    // 生成历史图片按钮
    handleCommand(command, item, subItem) {
      switch (command) {
        case '1':
          this.editForm.prompt = item.prompt
          break
        case '2':
          this.editForm = item
          break
        case '3':
          this.previewImageUrl = this.downloadUrl + subItem.imageId
          this.showImageViewer = true
          break
        default:
          break
      }
    },
    // 开始生成
    startGenerate() {
      this.$refs.form.validate(async(valid) => {
        if (valid) {
          if (!this.editForm.frameId) {
            this.$set(this.editForm, 'frameId', this.editForm['id'])
          }
          delete this.editForm['id']
          textToImages(this.editForm).then(_ => {
            this.generateLoading = true
            // 清空生成历史下标
            this.currentGenerateHistoryImageId = null
            // 清空选中的历史镜头下标
            this.currentHistoryImage = null
            this.generatingList = []
            for (let i = 0; i < this.editForm.createNum; i++) {
              this.generatingList.push({ ...this.editForm, imageId: '' })
            }
            // 判断当前任务是否在排队
            if (this.queueRemaining > 0) {
              this.$notify({
                title: '排队提示',
                message: `前面存在${this.queueRemaining}条任务,生成时间可能较长,请耐心等待~`,
                type: 'warning'
              })
            }
          })
        }
      })
    },
    // 开启webSocket 监听任务
    handleWs() {
      this.ws = new WS({
        url: `${wsUrl}${this.username}`
      })
      // 事件监听
      this.ws.on('open', () => {
        console.log('连接成功')
      })
      this.ws.on('message', data => {
        // console.log('收到消息:', data)
        const jsonData = data.data
        switch (data.type) {
          case 'status':
            this.queueRemaining = jsonData['queue_remaining']
            console.log('当前正在执行的任务数: ', this.queueRemaining)
            break
          case 'progress':
            // this.generateLoading = true
            break
          case 'executing':
            console.log('生成完成======', jsonData)
            if (jsonData && !jsonData['node']) {
              // 任务完成
              this.generateLoading = false
              // 更新生成历史
              this.queryGenerateHistory()
              // 根据镜头id判断，消息是否返回时当前镜头的任务
              console.log('当前任务id', jsonData['frameId'], '当前镜头id', this.editForm['frameId'])
              if (jsonData['frameId'] !== this.editForm['frameId']) return
              for (let i = 0; i < this.generatingList.length; i++) {
                const item = this.generatingList[i]
                const data = jsonData['result'][i]
                this.$set(item, 'imageId', data['imageId'])
                this.$set(item, 'taskStatus', '01')
              }
              console.log('生成列表', this.generatingList)
              // 默认选中第一张
              this.currentGenerateImage = 0
            }
            break
          case 'execution_start':
            this.generateLoading = true
            break
        }
      })
      this.ws.on('reconnect', count => console.log(`第 ${count} 次重连...`))
      this.ws.on('error', error => {
        console.log(error, '连接失败')
        this.generateLoading = false
        // 将所有生成中的图片状态改为失败
        if (this.generatingList.length === 0) return
        this.generatingList.forEach(item => {
          item.taskStatus = '02'
        })
      })
      this.ws.on('close', close => {
        console.log(close, '连接关闭')
        this.generateLoading = false
        // 将所有生成中的图片状态改为失败
        if (this.generatingList.length === 0) return
        this.generatingList.forEach(item => {
          item.taskStatus = '02'
        })
      })
    },
    // 格式化画面比例显示
    formatterPicture(val) {
      return this.pictureScaleList.find(item => item.code === val).name
    },
    // 格式化角色显示
    formatterRoleName(val) {
      if (!val) return '-'
      const strArr = []
      val.forEach(item => {
        strArr.push(item.name)
      })
      return strArr.join('、')
    },
    // 添加镜头
    handleAddLens(item, index) {
      this.$baseConfirm('确认添加镜头?', '提示', async() => {
        const params = {}
        if (item) {
          // 每个镜头前面添加
          this.$set(params, 'frameId', item['id'])
          this.$set(params, 'frameBeforeOrAfter', '01')
        } else {
          // 最后一个镜头后面添加
          this.$set(params, 'frameId', this.allLensList[this.allLensList.length - 1].id)
          this.$set(params, 'frameBeforeOrAfter', '02')
        }
        await addLensFrame(params)
        // 重新查询镜头数据
        this.lensFrameChangeReloadData(!item ? index + 1 : index)
      })
    },
    // 选中镜头
    handleSelectLens(index) {
      if (this.currentLensIndex === index) return
      this.currentLensIndex = index
      // 组合镜头数据
      this.handleShotDataCombination(index)
      // 清空正在生成数组列表
      this.generatingList = []
      // 清空选中的生成历史图片id
      this.currentGenerateHistoryImageId = null
      // 清空选中的生成之后的图片id
      this.currentGenerateImage = null
      // 默认选中历史镜头第一张
      this.currentHistoryImage = 0
      // 查询任务进度
      this.handleQueryProgress()
      // 如果选中镜头不存在随机种子,则手动生成
      if (this.$baseLodash.isEmpty(this.editForm['seed'])) {
        this.handleRandomGenerate()
      }
      this.queryLensSettingCoverHistory()
      this.queryGenerateHistory()
    },
    // 调用查询任务进度
    handleQueryProgress() {
      queryUserFrameProgress({ frameId: this.editForm['id'] || this.editForm['frameId'] }).then(res => {
        const { taskList, typeProgress } = res.data
        this.generateLoading = typeProgress === '01'
        if (typeProgress === '01') {
          // 清空任务数据
          this.generatingList = []
          // 清空选中的历史镜头下标
          this.currentHistoryImage = null
          // 存在进行中的任务,根据数据中的createNum 设置生成数组数据
          const taskData = taskList[0]
          this.editForm = { ...taskData }
          for (let i = 0; i < taskData.createNum; i++) {
            this.generatingList.push({ ...taskData, imageId: '' })
          }
        }
      })
    },
    // 向上移动镜头
    handleLenUp(item, index) {
      if (index === 0) {
        this.$baseMessage.error('已经是第一个镜头!')
        return
      }
      this.$baseConfirm('确认将该镜头向上移动?', '提示', async() => {
        // 调用接口移动镜头
        const { code, msg } = await moveLensFrame({ frameBeforeOrAfter: '01', frameId: item['id'] })
        code === 200 ? this.$baseMessage.success(msg || '向上移动成功!') : this.$baseMessage.error(msg || '向上移动失败!')
        // 选中上移
        this.lensFrameChangeReloadData(index - 1)
      })
    },
    // 向下移动镜头
    handleLenDown(item, index) {
      if (index === this.allLensList.length - 1) {
        this.$baseMessage.error('已经是最后一个镜头!')
        return
      }
      this.$baseConfirm('确认将该镜头向下移动?', '提示', async() => {
        // 调用接口移动镜头
        const { code, msg } = await moveLensFrame({ frameBeforeOrAfter: '02', frameId: item['id'] })
        code === 200 ? this.$baseMessage.success(msg || '向下移动成功!') : this.$baseMessage.error(msg || '向下移动失败!')
        // 选中下移
        this.lensFrameChangeReloadData(index + 1)
      })
    },
    // 镜头顺序改变后刷新数据
    lensFrameChangeReloadData(index) {
      queryLensListByFrameId({ lensId: this.selectLens['lensId'] }).then(res => {
        this.allLensList = res.data
        // 组合镜头数据
        this.handleShotDataCombination(index)
        // 选中当前下标
        this.handleSelectLens(index)
        // this.$nextTick(() => {
        //   // 滑动到对应镜头的位置
        //   const element = document.getElementById(`lensFrame${index}`)
        //   element.scrollIntoView({ behavior: 'smooth' })
        // })
      })
    },
    // 删除镜头
    handleLensFrameDelete(item) {
      this.$baseConfirm('确认删除该镜头?', '提示', async() => {
        // 调用接口删除镜头
        const { code, msg } = await deleteLensFrame({ frameId: item['id'] })
        code === 200 ? this.$baseMessage.success(msg || '删除成功!') : this.$baseMessage.error(msg || '删除失败!')
        // 刷新数据
        this.lensFrameChangeReloadData(this.currentLensIndex === this.allLensList.length - 1 ? this.currentLensIndex - 1 : this.currentLensIndex)
      })
    },
    // 图片历史镜头记录点击
    handleSelectHistory(index) {
      this.currentHistoryImage = index
      this.currentHistoryImageData = this.historyLensList[index] || {}
      // 清空正在生成数组列表
      this.generatingList = []
      // 清空生成历史图片下标
      this.currentGenerateHistoryImageId = null
      // 清空选中的生成之后的图片id
      this.currentGenerateImage = null
    },
    // 提示词复用
    handleReusePrompt(history) {
      console.log(history, 7878)
      this.editForm.prompt = history.prompt
    },
    // 放大图片
    handleFull(data) {
      this.previewImageUrl = this.downloadUrl + data['imageId']
      this.showImageViewer = true
    },
    // 镜头数据组合
    handleShotDataCombination(index) {
      this.editForm = Object.assign({}, this.allLensList[index])
      if (!this.editForm['steps']) {
        this.$set(this.editForm, 'steps', 30)
      }
      if (!this.editForm['cfg']) {
        this.$set(this.editForm, 'cfg', 5.50)
      }
      if (!this.editForm['createNum']) {
        this.$set(this.editForm, 'createNum', '1')
      }
      if (!this.editForm['pictureScale']) {
        this.$set(this.editForm, 'pictureScale', '2')
      }
      if (!this.editForm['isLink']) {
        this.$set(this.editForm, 'isLink', '1')
      }
      if (!this.editForm['imageWidth']) {
        this.$set(this.editForm, 'imageWidth', '1920')
      }
      if (!this.editForm['imageHeight']) {
        this.$set(this.editForm, 'imageHeight', '1080')
      }
      if (!this.editForm['seed']) {
        this.handleRandomGenerate()
      }
      console.log('当前文生图表单的内容:', this.editForm)
    },
    // 提示词区域切换
    promptFullChange() {
      this.isFullscreen = fullscreen.isFullscreen
    }
  }
}

</script>

<style scoped lang="scss">
// 文生图编辑区
.edit-content {
  padding: 18px 12px;
  box-sizing: border-box;
  >span {
    height: 20px;
    line-height: 20px;
  }
  .edit-form-content {
    margin-top: 10px;
    overflow-y: auto;
    height: calc( 100% - 90px - 20px );
    .create-num-content {
      align-items: center;
      .create-num-item {
        padding: 5px 10px;
        border-radius: 5px;
        cursor: pointer;
        flex: 1;
        background: #272C36;
        border: 1px solid #39414E;
        color: #686B7A;
        margin-right: 10px;
        text-align: center;
        &.active {
          color: #FFFFFF;
          border: 1px solid #FFFFFF;
        }
      }
    }
    .prompt-content {
      position: relative;
      background: #272C36;
      border: 1px solid #39414E;
      border-radius: 5px;
      ::v-deep {
        textarea {
          border: none;
          resize: none;
        }
      }
      &-full {
        ::v-deep {
          textarea {
            height: calc(100vh - 50px);
          }
        }
      }
      .prompt-toolbar {
        margin-top: 10px;
        padding: 10px;
        box-sizing: border-box;
        >.svg-icon {
          width: 18px;
          height: 18px;
          cursor: pointer;
          margin-right: 8px;
          color: #606372;
        }
      }
      .change-loading {
        position: absolute;
        bottom: 5px;
        right: 5px;
      }
    }
    .prompt-language {
      position: absolute;
      top: -30px;
      right: 0;
      width: 18px;
      height: 18px;
      cursor: pointer;
    }
    .prompt-recommend {
      position: absolute;
      right: 25px;
      top: -30px;
      width: 18px;
      height: 18px;
      cursor: pointer;
    }
    .upload-demo {
      width: 100%;
      ::v-deep {
        .el-upload {
          width: 100%;
        }
        .el-upload-dragger {
          background: #272C36 !important;
          border-color: #5C6872;
          width: 100%;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          color: #B6C7D1;
          padding: 0 10px;
          box-sizing: border-box;
          overflow: hidden;
          height: 80px;
          font-size: 12px;
          >div {
            line-height: 15px;
          }
          >i {
            font-size: 20px;
          }
          em {
            font-style: normal;
            color: $base-color-default;
          }
        }
      }
    }
    .prompt-lens-icon {
      position: absolute;
      top: -30px;
      right: 0;
      width: 18px;
      height: 18px;
      cursor: pointer;
      color: #FFFFFF;
    }
    .prompt-image {
      position: relative;
      width: 90px;
      height: 90px;
      border-radius: 5px;
      overflow: hidden;
      cursor: pointer;
      ::v-deep {
        .el-image {
          width: 100%;
          height: 100%;
        }
      }
      &:hover {
        >.prompt-image-toolbar {
          display: flex;
        }
      }
      .prompt-image-toolbar {
        position: absolute;
        left: 0;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
        background: rgba(18, 20, 24, 0.50);
        align-items: center;
        justify-content: space-between;
        padding: 8px 5px;
        box-sizing: border-box;
        display: none;
        >i {
          font-size: 14px;
          cursor: pointer;
        }
      }
    }
  }
  .edit-bottom-bar {
    padding-top: 20px;
    padding-bottom: 10px;
    box-sizing: border-box;
    align-items: center;
    justify-content: center;
    height: 40px;
    .svg-icon {
      width: 24px;
      height: 24px;
      cursor: pointer;
    }
  }
}
</style>
